package org.az.netty_study.p09_netty组件之ByteBuf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.az.netty_study.ByteBufferUtil;

/**
 * netty中的ByteBuf，是对nio中ByteBuffer的封装和增强
 * 启动最重要的一个增强是，ByteBuf可以根据数据量动态扩容和缩容
 * 他们的角色，是一样的，都是从channel读取数据时，数据暂时存放的地方
 */
public class _1_ByteBuf初体验 {
    public static void main(String[] args) {
        /**
         * ByteBuf容量的动态调整
         */
        //这里的ByteBuf是直接内存
        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        //打印发现，不传参数，ByteBuf容量默认是256个字节
        ByteBufferUtil.logBuf(buf);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 300; i++) {
            sb.append("a");
        }
        //写入300个字节后，发现容量变成了512
        buf.writeBytes(sb.toString().getBytes());
        ByteBufferUtil.logBuf(buf);

        /**
         * 直接内存和堆内存
         *  堆内存:分配效率高,读写效率低，受GC影响
         *  直接内存：系统内存，分配效率低，读写效率高(零拷贝，内存隐射)，不受GC影响
         * ByteBuf默认使用直接内存
         */
        //堆内存
        ByteBuf heapBuf = ByteBufAllocator.DEFAULT.heapBuffer(10);
        //直接内存
        ByteBuf directBuf = ByteBufAllocator.DEFAULT.directBuffer(10);

        /**
         * 池化
         *  直接内存由于是操作系统内存，分配和销毁效率低
         *  所以可以采用池化的思想(想想线程池、数据库连接池)来管理直接内存，使用时从池里拿取内存，销毁时归还内存
         * 使用下面vm参数来选择开启或关闭池化功能(4.1后，非安卓平台默认开启池化)
         * -Dio.netty.allocator.type={unpooled|pooled}
         */
        //打印发现directBuf类型是:PooledUnsafeDirectByteBuf，Pooled表示池化，Direct表示直接内存
        System.out.println(directBuf.getClass());
        //heapBuf类型:PooledUnsafeHeapByteBuf，说明堆内存也是默认池化
        System.out.println(heapBuf.getClass());
        /**
         * ByteBuf跟ByteBuffer一样，也有两个指针
         * 这不过这两个指针不是position和limit，而是读指针和写指针(ByteBuffer读写指针共用position)
         */
    }
}
